﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Net;

namespace PFAGame.NetworkingGame
{
    class PlayerNet
    {
        #region Fields

        public APlayer player
        {
            get;
            private set;
        }

        private bool isInit = false;

        #endregion

        public PlayerNet()
        {

        }

        #region Methods

        public void Serialize(PacketWriter packetWriter)
        {
            Serialize(this.player, packetWriter);
        }

        public static void Serialize(APlayer player, PacketWriter packetWriter)
        {
            if (packetWriter == null)
                throw new ArgumentNullException("packetWriter");

            if (player != null)
            {
                packetWriter.Write(player.Position);
                packetWriter.Write(player.Orientation);
                packetWriter.Write(player.Life);
                packetWriter.Write(player.Level);
                packetWriter.Write((int) player.playerCLass);
            }
        }

        public void Deserialize(PacketReader packetReader, string gamerTag)
        {
            if (packetReader == null)
                throw new ArgumentNullException("packetWriter");
            if (isInit == false)
            {
                Vector2 pos = packetReader.ReadVector2();
                Vector2 ori = packetReader.ReadVector2();
                float life = packetReader.ReadSingle();
                int lvl = packetReader.ReadInt32();

                switch ((e_class) packetReader.ReadInt32())
                {
                    case e_class.SPECIALISTE:
                        this.player = new Specialiste();
                        break;
                    case e_class.BOURRIN:
                        this.player = new Bourrin();
                        break;
                    default:
                        this.player = new Specialiste();
                        break;
                }

                this.player.init();
                this.player.Position = pos;
                this.player.Orientation = ori;
                this.player.Life = life;
                this.player.Level = lvl;

                {
                    int n = 0;

                    foreach (char c in gamerTag)
                        this.player.Id += (c * ++n);
                }
                GameplayScreen.Singleton.DicoPlayer.Add(player.Id, player);
                isInit = true;
            }
            else
            {
                player.Position = packetReader.ReadVector2();
                player.Orientation = packetReader.ReadVector2();
                player.Life = packetReader.ReadSingle();
                player.Level = packetReader.ReadInt32();
                player.playerCLass = (e_class) packetReader.ReadInt32();
            }
        }

        internal void UpdateMob(PacketReader packetReader)
        {
            if (packetReader == null)
                throw new ArgumentNullException("packetReader");

            var dicoMob = GameplayScreen.Singleton.DicoMob;
            var tmpDico = new Dictionary<int, bool>();
            int mobn = packetReader.ReadInt32();

            foreach (AMob mob in dicoMob.Values)
            {
                tmpDico[mob.Id] = false;
            }
            for (int i = 0; i < mobn; i++)
            {
                MobNet networkMob = new MobNet(packetReader);

                if (dicoMob.ContainsKey(networkMob.Id) == false)
                {
                    AMob mob = MobFactory.Create(networkMob.Type, networkMob.Position.X, networkMob.Position.Y);

                    mob.init();
                    mob.Id = networkMob.Id;
                    dicoMob[mob.Id] = mob;
                }
                else
                {
                    AMob mob = dicoMob[networkMob.Id];

                    mob.Position = networkMob.Position;
                    mob.Orientation = networkMob.Orientation;
                    mob.state = networkMob.State;
                    tmpDico[mob.Id] = true;
                }
            }
            foreach (int key in tmpDico.Keys)
            {
                if (tmpDico[key] == false)
                    dicoMob.Remove(key);
            }
        }

        internal void UpdateLoot(PacketReader packetReader)
        {
            if (packetReader == null)
                throw new ArgumentNullException("packetReader");

            var dicoLoot = GameplayScreen.Singleton.DicoLoot;
            var tmpDico = new Dictionary<int, bool>();
            int lootn = packetReader.ReadInt32();

            foreach (ALoot proj in dicoLoot.Values)
            {
                tmpDico[proj.Id] = false;
            }
            for (int i = 0; i < lootn; i++)
            {
                LootNet networkloot = new LootNet(packetReader);

                if (dicoLoot.ContainsKey(networkloot.Id) == false)
                {
                    ALoot loot = LootFactory.Create(networkloot.TypeLoot);

                    loot.init();
                    loot.Id = networkloot.Id;
                    loot.Position = networkloot.Position;
                    dicoLoot[loot.Id] = loot;
                }
                else
                {
                    tmpDico[networkloot.Id] = true;
                }
            }
            foreach (int key in tmpDico.Keys)
            {
                if (tmpDico[key] == false)
                    dicoLoot.Remove(key);
            }
        }

        internal void UpdateProjectile(PacketReader packetReader)
        {
            if (packetReader == null)
                throw new ArgumentNullException("packetReader");

            var dicoProj = GameplayScreen.Singleton.DicoProjectile;
            var tmpDico = new Dictionary<int, bool>();
            int projn = packetReader.ReadInt32();

            foreach (AProjectile proj in dicoProj.Values)
            {
                tmpDico[proj.Id] = false;
            }
            for (int i = 0; i < projn; i++)
            {
                ProjNet netowrkProj = new ProjNet(packetReader);

                if (dicoProj.ContainsKey(netowrkProj.Id) == false)
                {
                    AProjectile projectile = ProjectileFactory.Create(netowrkProj.ProjType);

                    projectile.Orientation = netowrkProj.Orientation;
                    projectile.init();
                    projectile.Id = netowrkProj.Id;
                    projectile.Position = netowrkProj.Position;
                    dicoProj[projectile.Id] = projectile;
                }
                else
                {
                    AProjectile projectile = dicoProj[netowrkProj.Id];

                    projectile.Position = netowrkProj.Position;
                    projectile.Orientation = netowrkProj.Orientation;
                    tmpDico[projectile.Id] = true;
                }
            }
            foreach (int key in tmpDico.Keys)
            {
                if (tmpDico[key] == false)
                    dicoProj.Remove(key);
            }
        }

        internal void DeserializeShootData(PacketReader packetReader)
        {
            if (packetReader == null)
                throw new ArgumentNullException("packetReader");

            PFAGame.Specialiste.ShootData networkProjectile = new PFAGame.Specialiste.ShootData();
            AProjectile projectile = ProjectileFactory.Create(AObject.e_object.PROJECTILESPEC);

            networkProjectile.Deserialize(packetReader);
            projectile.Orientation = networkProjectile.Orientation;
            projectile.init();
            projectile.Position = networkProjectile.Position;
            projectile.Dammage = networkProjectile.Dammage;
            projectile.Speed = networkProjectile.Speed;
            GameplayScreen.Singleton.ProjectileList.Add(projectile);
        }

        #region Map

        internal void InitializeWorld(PacketReader packetReader)
        {
            if (packetReader == null)
                throw new ArgumentNullException("packetReader");

            int seed = packetReader.ReadInt32();
            GameplayScreen.Singleton.MapP.Seed = seed;

            int lvl = packetReader.ReadInt32();
            GameplayScreen.Singleton.CurrentLevel = lvl;

            e_GameMode gameMode = (e_GameMode) packetReader.ReadInt32();
            GameplayScreen.Singleton.gameMode = gameMode;
        }

        internal void UpdateWorld(PacketReader packetReader)
        {
            int seed;

            // TODO : Continuer a implementer
            if (packetReader == null)
                throw new ArgumentNullException("packetReader");
            seed = packetReader.ReadInt32();
        }

        #endregion

        #endregion
    }
}
